home *** CD-ROM | disk | FTP | other *** search
/ Visual Cafe 3 / Visual Cafe 3.ISO / Vcafe / JFC.bin / AppContext.java < prev    next >
Text File  |  1998-06-30  |  8KB  |  222 lines

  1. /*
  2.  * @(#)AppContext.java    1.4 98/02/26
  3.  * 
  4.  * Copyright 1993-1997 Sun Microsystems, Inc. 901 San Antonio Road, 
  5.  * Palo Alto, California, 94303, U.S.A.  All Rights Reserved.
  6.  * 
  7.  * This software is the confidential and proprietary information of Sun
  8.  * Microsystems, Inc. ("Confidential Information").  You shall not
  9.  * disclose such Confidential Information and shall use it only in
  10.  * accordance with the terms of the license agreement you entered into
  11.  * with Sun.
  12.  * 
  13.  * CopyrightVersion 1.2
  14.  * 
  15.  */
  16.  
  17. package com.sun.java.swing;
  18.  
  19. import java.util.Hashtable;
  20.  
  21. /**
  22.  * The AppContext is a per-SecurityContext table which stores application
  23.  * service instances.  (If you are not writing an application service, or
  24.  * don't know what one is, please do not use this class.)  The AppContext
  25.  * allows applet access to what would otherwise be potentially dangerous
  26.  * services, such as the ability to peek at EventQueues or change the
  27.  * look-and-feel of a Swing application.<p>
  28.  *
  29.  * Most application services use a singleton object to provide their
  30.  * services, either as a default (such as getSystemEventQueue or 
  31.  * getDefaultToolkit) or as static methods with class data (System).
  32.  * The AppContext works with the former method by extending the concept
  33.  * of "default" to be SecurityContext-specific.  Application services
  34.  * lookup their singleton in the AppContext; if it hasn't been created,
  35.  * the service creates the singleton and stores it in the AppContext.<p>
  36.  *
  37.  * For example, here we use have a Foo service, with its pre-AppContext
  38.  * code:<p>
  39.  * <code><pre>
  40.  *    public class Foo {
  41.  *        private static Foo defaultFoo = new Foo();
  42.  *
  43.  *        public static Foo getDefaultFoo() {
  44.  *            return defaultFoo;
  45.  *        }
  46.  *
  47.  *    ... Foo service methods
  48.  *    }</pre></code><p>
  49.  *
  50.  * The problem with the above is that the Foo service is global in scope,
  51.  * so that applets and other untrusted code can execute methods on the
  52.  * single, shared Foo instance.  The Foo service therefore either needs
  53.  * to block its use by untrusted code using a SecurityManager test, or
  54.  * restrict its capabilities so that it doesn't matter if untrusted code
  55.  * executes it.<p>
  56.  *
  57.  * Here's the Foo class written to use the AppContext:<p>
  58.  * <code><pre>
  59.  *    public class Foo {
  60.  *        public static Foo getDefaultFoo() {
  61.  *            Foo foo = (Foo)AppContext.getAppContext().get(Foo.class);
  62.  *            if (foo == null) {
  63.  *                foo = new Foo();
  64.  *                getAppContext().put(Foo.class, foo);
  65.  *            }
  66.  *            return foo;
  67.  *        }
  68.  *
  69.  *    ... Foo service methods
  70.  *    }</pre></code><p>
  71.  *
  72.  * Since a separate AppContext exists for each SecurityContext, trusted
  73.  * and untrusted code have access to different Foo instances.  This allows
  74.  * untrusted code access to "system-wide" services -- the service remains
  75.  * within the security "sandbox".  For example, say a malicious applet 
  76.  * wants to peek all of the key events on the EventQueue to listen for
  77.  * passwords; if separate EventQueues are used for each SecurityContext
  78.  * using AppContexts, the only key events that applet will be able to
  79.  * listen to are its own.  A more reasonable applet request would be to
  80.  * change the Swing default look-and-feel; with that default stored in
  81.  * an AppContext, the applet's look-and-feel will change without 
  82.  * disrupting other applets or potentially the browser itself.<p>
  83.  *
  84.  * Because the AppContext is a facility for safely extending application
  85.  * service support to applets, none of its methods may be blocked by a
  86.  * a SecurityManager check in a valid Java implementation.  Applets may
  87.  * therefore safely invoke any of its methods without worry of being 
  88.  * blocked.
  89.  *
  90.  * @author  Thomas Ball
  91.  * @version 1.4 02/26/98
  92.  */
  93. final class AppContext {
  94.  
  95.     /* Since the contents of an AppContext are unique to each Java 
  96.      * session, this class should never be serialized. */
  97.  
  98.     // A map of AppContexts, referenced by SecurityContext.
  99.     private static Hashtable security2appContexts = new Hashtable(2);
  100.  
  101.     // A handle to be used when the SecurityContext is null.
  102.     private static Object nullSecurityContext = new Object();
  103.  
  104.     /*
  105.      * The hashtable associated with this AppContext.  A private delegate
  106.      * is used instead of subclassing Hashtable so as to avoid all of
  107.      * Hashtable's potentially risky methods, such as clear(), elements(),
  108.      * putAll(), etc.  (It probably doesn't need to be final since the
  109.      * class is, but I don't trust the compiler to be that smart.)
  110.      */
  111.     private final Hashtable table;
  112.  
  113.     private AppContext(Object securityContext) {
  114.         table = new Hashtable(2);
  115.         security2appContexts.put(securityContext, this);
  116.     }
  117.  
  118.     /**
  119.      * Returns the appropriate AppContext for the caller, 
  120.      * as determined by its SecurityContext.  
  121.      *
  122.      * @returns the AppContext for the caller.
  123.      * @see     java.lang.SecurityManager#getSecurityContext
  124.      * @since   JDK1.2
  125.      */
  126.     public static AppContext getAppContext() {
  127.         // Get security context, if any.
  128.  
  129.         Object securityContext = nullSecurityContext;
  130. /*
  131.  Commenting out until we can reliably compute AppContexts
  132.  
  133.         SecurityManager sm = System.getSecurityManager();
  134.         if (sm != null) {
  135.             Object context = 
  136.                 System.getSecurityManager().getSecurityContext();
  137.             if (context != null) {
  138.                 securityContext = context;
  139.             }
  140.         }
  141.         */
  142.  
  143.         // Map security context to AppContext.
  144.  
  145.         AppContext appContext =
  146.             (AppContext)security2appContexts.get(securityContext);
  147.         if (appContext == null) {
  148.             appContext = new AppContext(securityContext);
  149.             security2appContexts.put(securityContext, appContext);
  150.         }
  151.  
  152.         return appContext;
  153.     }
  154.  
  155.     /**
  156.      * Returns the value to which the specified key is mapped in this context.
  157.      *
  158.      * @param   key   a key in the AppContext.
  159.      * @return  the value to which the key is mapped in this AppContext;
  160.      *          <code>null</code> if the key is not mapped to any value.
  161.      * @see     #put(Object, Object)
  162.      * @since   JDK1.2
  163.      */
  164.     public Object get(Object key) {
  165.         return table.get(key);
  166.     }
  167.  
  168.     /**
  169.      * Maps the specified <code>key</code> to the specified 
  170.      * <code>value</code> in this AppContext.  Neither the key nor the 
  171.      * value can be <code>null</code>.
  172.      * <p>
  173.      * The value can be retrieved by calling the <code>get</code> method 
  174.      * with a key that is equal to the original key. 
  175.      *
  176.      * @param      key     the AppContext key.
  177.      * @param      value   the value.
  178.      * @return     the previous value of the specified key in this 
  179.      *             AppContext, or <code>null</code> if it did not have one.
  180.      * @exception  NullPointerException  if the key or value is
  181.      *               <code>null</code>.
  182.      * @see     #get(Object)
  183.      * @since   JDK1.2
  184.      */
  185.     public Object put(Object key, Object value) {
  186.         return table.put(key, value);
  187.     }
  188.  
  189.     /**
  190.      * Removes the key (and its corresponding value) from this 
  191.      * AppContext. This method does nothing if the key is not in the
  192.      * AppContext.
  193.      *
  194.      * @param   key   the key that needs to be removed.
  195.      * @return  the value to which the key had been mapped in this AppContext,
  196.      *          or <code>null</code> if the key did not have a mapping.
  197.      * @since   JDK1.2
  198.      */
  199.     public Object remove(Object key) {
  200.         return table.remove(key);
  201.     }
  202.  
  203.     /**
  204.      * Returns a string representation of this AppContext.
  205.      * @since   JDK1.2
  206.      */
  207.     public String toString() {
  208.         Object securityContext = nullSecurityContext;
  209.         SecurityManager sm = System.getSecurityManager();
  210.         if (sm != null) {
  211.             Object context = 
  212.                 System.getSecurityManager().getSecurityContext();
  213.             if (context != null) {
  214.                 securityContext = context;
  215.             }
  216.         }
  217.         String contextName = (securityContext.equals(nullSecurityContext) ?
  218.             "null" : securityContext.toString());
  219.     return getClass().getName() + "[SecurityContext=" + contextName + "]";
  220.     }
  221. }
  222.